home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / a86v307c.arc / 10RELOC.DOC next >
Text File  |  1987-07-13  |  32KB  |  641 lines

  1. CHAPTER 10   RELOCATION AND LINKAGE                       10-1
  2.  
  3. Since this is the start of the A86VxxxC.ARC file, I'll repeat 
  4. here that the entire A86 package is Copyright (C)1986--1987 Eric 
  5. Isaacson.  All rights reserved.  If this is all you've got, you 
  6. need to get A86VxxxA.ARC, and A86VxxxB.ARC, which contain the 
  7. program and the first part of the manual. 
  8.  
  9. A86 allows you to produce either .COM files, which can be run 
  10. immediately as standalone programs, or .OBJ files, to be fed to 
  11. the MS-DOS LINK program.  In this chapter I'll discuss .OBJ mode 
  12. of A86.  
  13.  
  14.  
  15. .OBJ Production Made Easy 
  16.  
  17. I'll start by giving you the minimum amount of information you 
  18. need to know to produce .OBJ files.  If you are writing short 
  19. interface routines, and do not want to concern yourself with the 
  20. esoterica of OBJ files (segments, groups, publics, etc.), you can 
  21. survive quite nicely by reading only this section.  
  22.  
  23. There are two ways you can cause A86 to produce a .OBJ file as 
  24. its object output.  One way is to explicitly give .OBJ as the 
  25. output file name: for example, you can assemble the source file 
  26. FOO.8 by giving the command "A86 FOO.8 FOO.OBJ".  The other way 
  27. is to specify the switch +O (letter O not digit 0).  This is 
  28. illustrated by the invocation "A86 +O FOO.8", which will have the 
  29. same effect as the first invocation.  
  30.  
  31. My design philosophy for .OBJ production is to accommodate two 
  32. types of user.  The first type of user is writing new code, to 
  33. link to other (usually high-level language) modules.  That person 
  34. should be able to write the module with a minimum of red tape, 
  35. and have A86 do the right thing.  The second type of user has 
  36. existing modules written for Intel/IBM assemblers, and wants to 
  37. port them to A86.  A86 should recognize and act upon all the 
  38. relocation directives (SEGMENT, GROUP, PUBLIC, EXTRN, NAME, END) 
  39. given.  The assembly should work even if several files, assembled 
  40. separately under the Intel/IBM assembler, are fed to a single A86 
  41. assembly.  You'll see if you read on through this entire chapter 
  42. that the multiple-files requirement causes A86 to interpret some 
  43. of the relocation directives a little differently (while 
  44. achieving compatible results).  
  45.  
  46. Let's suppose you're writing new code: for example, an interface 
  47. routine to the "C" language, that multiplies a 16-bit number by 
  48. 10.  "C" pushes the input number onto the stack, before calling 
  49. your routine.  Your code needs to get the number, multiply it by 
  50. 10, and return the answer in the AX register.  You can code it:
  51.  
  52. _MUL10:          ; "C" expects all public names to start with "_"
  53.   PUSH BP        ; "C" expects BP to be preserved
  54.   MOV BP,SP      ; we use BP to address the stack
  55.   MOV AX,[BP+4]  ; fetch the number N, beyond BP and the ret addr
  56.   ADD AX,AX      ; 2N
  57.   MOV BX,AX      ; 2N is saved in BX
  58.   ADD AX,AX      ; 4N
  59.   ADD AX,AX      ; 8N
  60.   ADD AX,BX      ; 8N + 2N = 10N
  61.   POP BP         ; BP is restored
  62.   RET            ; go back to caller 
  63.                                                           10-2
  64. These 11 lines can be your entire source file!  If you name the 
  65. file MUL10.8, A86 will create an object file MUL10.OBJ, that 
  66. conforms to the standard SMALL model of computation for high-
  67. level languages.  If you use RETF instead of RET (thus, by the 
  68. way, getting the operand from BP+6 instead of BP+4), the object 
  69. module will conform to the standard LARGE model of computation.  
  70. All the red-tape information required by the high-level language 
  71. is provided implicitly by A86.  I'll go through this information 
  72. in detail later, but you should need to read about it only if 
  73. you're curious.  
  74.  
  75. What happens if you need to access symbols outside the module 
  76. you're assembling?  If the type of the symbol is correctly 
  77. guessed from the instruction that refers to it, then you can 
  78. simply refer to it, and leave it undefined within the module.  
  79. For example, if A86 sees the instruction CALL PRINT with PRINT 
  80. undefined, it will assume that PRINT is a NEAR procedure.  If 
  81. PRINT is never defined within the module, A86 will act as if you 
  82. declared PRINT via the directive EXTRN PRINT:NEAR.  The address 
  83. of PRINT will be plugged into your instruction by LINK when it 
  84. combines A86's .OBJ file with the high-level language's .OBJ 
  85. files, to make the final program.  
  86.  
  87. In general, the undefined operand to any CALL or JMP instruction 
  88. is assumed to be NEAR.  The second (source) operand to a MOV or 
  89. arithmetic instruction is assumed to be ABS (i.e., an immediate 
  90. constant).  An undefined first (destination) operand is assumed 
  91. to be a simple memory variable, of the same size (BYTE or WORD) 
  92. as the register given in the second operand.  If your external 
  93. symbol does not comply with these guidelines, you need to declare 
  94. it with an EXTRN before you use it.  (You can also use EXTRN to 
  95. declare types of non-complying forward-references within your 
  96. module, as you'll see later.) 
  97.  
  98. At this point, if you're a casual user, I think you've read 
  99. enough to get going!  Read further only if you wish; or if you 
  100. get stuck, and need to master the esoterica.  
  101.  
  102.  
  103. Overview of Relocation and Linkage
  104.  
  105. When you assemble a program directly into a .COM file, the 
  106. program has just two forms: the source program, that you can 
  107. understand, and the .COM file, that the computer can "understand" 
  108. (i.e., execute).  A .OBJ file is an intermediate format: neither 
  109. you nor the (executing) computer can make sense out a .OBJ file; 
  110. only programs like LINK interpret .OBJ files.  The purpose of a 
  111. .OBJ file is to allow you to assemble or compile just a part of a 
  112. program.  The other parts (also in the form of .OBJ files) can be 
  113. produced at a different time; often by a different assembler or 
  114. compiler, whose source files are in a different language.  It's 
  115. easy to see where the word "linkage" comes from: the LINK program 
  116. puts the pieces of a program together.  The "relocation" comes 
  117. because the assembler or compiler that makes a given program 
  118. piece doesn't know how many other pieces will come before it, or 
  119. how big the other pieces will be.  Each piece is constructed as 
  120. if it started at location 0 within the program; then LINK 
  121. "relocates" the piece to its true location.  
  122.                                                           10-3
  123. Many of the relocation features of 86 assembly language are 
  124. couched in terms of LINK's point of view, so we must look at the 
  125. way LINK sees things.  LINK calls a .OBJ file an "object module", 
  126. or just "module".  Each module has a NAME, that can be referred 
  127. to when LINK issues diagnostic messages, such as error messages 
  128. and symbol maps.  If a program symbol is used only within a 
  129. single module, it does not need to be given to LINK, except 
  130. possibly to pass along to a symbolic debugger.  On the other 
  131. hand, if a program symbol is defined in one module and referenced 
  132. in other modules, then LINK needs to know the name of the symbol, 
  133. so it can resolve the references.  Such a symbol is PUBLIC in the 
  134. module in which it is defined; it is "external" in the other 
  135. modules, containing references to it.  Finally, exactly one 
  136. module in a program must contain the starting location for the 
  137. program; that module is called the "main module", and it must 
  138. supply the starting address (which is not necessarily at the 
  139. beginning of the module).  
  140.  
  141. In the 86 family of microprocessors, the LINK system also does 
  142. much to manage the memory segments that a program will fit into, 
  143. and get its data from.  The (grotesquely ornate) level of support 
  144. for segmentation was dictated by Intel when it specified (and IBM 
  145. and the compiler-makers accepted) the format that .OBJ files will 
  146. have.  I attended the fateful meeting at Intel, in which the 
  147. crucial design decisions were made.  I regret to say that I sat 
  148. quietly, while engineers more senior than I applied their fertile 
  149. imaginations to construct fanciful scenarios which they felt had 
  150. to be supported by LINK.  Let's now review the resulting 
  151. segmentation model.  
  152.  
  153. The parts of a program, as viewed by LINK, come in three 
  154. different sizes: they can be (1) pieces of a single segment, (2) 
  155. an entire single segment, or (3) a sequence of consecutive 
  156. segments in 86 memory.  Size (1) should have been called 
  157. something like FRAGMENT, but is instead called SEGMENT.  Size (2) 
  158. should have been called SEGMENT, but is instead called GROUP.  
  159. Size (3) should have been called "group", but is instead called 
  160. "class".  Let me cling to the sensible terminology for one more 
  161. paragraph, while I describe the worst scenario Intel wanted to 
  162. support; then when I discuss individual directives, I'll 
  163. regretfully revert to the official terminology.  
  164.                                                           10-4
  165. The scenario is as follows: suppose you have a program that 
  166. occupies about 100K bytes of memory.  The program contains a core 
  167. of 20K bytes of utility routines that every part of the program 
  168. calls.  You'd like every part of the program to be able to call 
  169. these routines, using the NEAR form to save memory.  By gum, you 
  170. can do it!  You simply(!) slice the program into three fragments: 
  171. the utility routines will go into fragment U, and the rest of the 
  172. program will be split into equal-sized 40K-byte fragments A and 
  173. B.  Now you arrange the fragments in 8086 memory in the order 
  174. A,U,B.  The fragments A and U form a 60K-byte block, addressed by 
  175. a segment-register value G1, that points to the beginning of A.  
  176. The fragments U and B form another 60K-byte block addressed by a 
  177. segment-register value G2, that points to the beginning of U.  If 
  178. you set the CS register to G1 when A is executing, and G2 when B 
  179. is executing, the U fragment is accessible at all times.  Since 
  180. all direct JMPs and CALLs are encoded as relative offsets, the U-
  181. code will execute direct jumps correctly whether addressed by G1 
  182. with a huge offset, or G2 with a small offset.  Of course, if U 
  183. contains any absolute pointers referring to itself (such as an 
  184. indirect near JMP or CALL), you're in trouble.  
  185.  
  186. It's now been nine years since the fateful design meeting took 
  187. place, and I can report that the above scenario has never taken 
  188. place in the real world.  And I can state with some authority 
  189. that it never will.  The reason is that the only programs that 
  190. exceed 64K bytes in size are coded in high-level language, not 
  191. assembly language.  High-level language compilers follow a very, 
  192. very restricted segmentation model-- no existing model comes 
  193. remotely close to supporting the scheme suggested by the 
  194. scenario.  But the 86 assembly language can support it-- the 
  195. directives "G1 GROUP A,U" and "G2 GROUP B,U", followed by chunks 
  196. of code of the appropriate object size, headed by directives "A 
  197. SEGMENT", "B SEGMENT", and "U SEGMENT".  The LINK program is 
  198. supposed to sort things out according to the scenario; but I 
  199. can't say (and I have my doubts) if it actually succeeds in doing 
  200. so.  
  201.  
  202. The concept of "class" was added as an afterthought, to implement 
  203. the more sensible and usable features that outsiders thought 
  204. GROUPs were implementing;  namely, the ability to specify that 
  205. different (and disjoint!) segments occur consecutively in memory.  
  206. This allows programs to be arranged in a consistent manner-- for 
  207. example, with all program code followed by all static data 
  208. segments followed by all dynamically-allocated memory.  
  209.                                                           10-5
  210. The NAME Directive
  211.  
  212. Syntax:   NAME module_name
  213.  
  214. The NAME directive specifies that "module_name" be given to LINK 
  215. as the name of the module produced by this assembly.  The symbol 
  216. "module_name" can be used elsewhere in your program without 
  217. conflict: it can even, if you like, be a built-in assembler 
  218. mnemonic (e.g. "NAME MOV" is acceptable)!  
  219.  
  220. If you do not provide a NAME directive, A86 will use the name of 
  221. the output object file, without the .OBJ extension.   If you 
  222. provide more than one NAME directive, A86 will use the last one 
  223. given, with no error reported.  
  224.  
  225.  
  226.  
  227. The PUBLIC Directive
  228.  
  229. Syntax:   PUBLIC  sym1, sym2, sym3, ...
  230.           PUBLIC
  231.  
  232. The PUBLIC directive allows you to explicitly list the symbols 
  233. defined in this assembly, that can be used by other modules.  If 
  234. you do not give any PUBLIC directives in your program, A86 will 
  235. use every relocatable label and variable name in your program, 
  236. except local labels (the redefinable labels consisting of a 
  237. letter followed by digits: L7, M1, Q234, etc.).  Symbols EQUated 
  238. to constants, and symbols defined within structures and DATA 
  239. SEGMENTs, are not implicitly declared PUBLIC: you have to 
  240. explicitly include them in a PUBLIC directive.  
  241.  
  242. A86 maintains an internal flag, telling it whether to figure out 
  243. for itself which symbols are PUBLIC, or to let the program 
  244. explicitly declare them.  The flag starts out "implicit", and is 
  245. set to "explicit" only if A86 sees a PUBLIC directive with no 
  246. names at all, or a PUBLIC directive containing at least one name 
  247. that would have been implicitly made PUBLIC.  
  248.  
  249. If you are writing new code, you'll probably want to keep the 
  250. flag "implicit".  You use the PUBLIC directive only for those 
  251. symbols which have the form of local labels, but aren't (e.g., a 
  252. memory variable I1987 for 1987 income); and for absolute values 
  253. that are globally accessed -- e.g. specify "PUBLIC 
  254. OPEN_FILES_LIMIT" for a symbol defined as "OPEN_FILES_LIMIT EQU 
  255. 20".  
  256.  
  257. If you are porting existing code, that code will already have 
  258. PUBLIC directives in it, and A86 will go to "explicit" mode, 
  259. duplicating the functionality of other assemblers.  
  260.  
  261. The PUBLIC directive with no names is used to force "explicit" 
  262. mode, thus causing (if there are no further PUBLICs with names) 
  263. the .OBJ file to declare no symbols PUBLIC.  
  264.                                                           10-6
  265. There is another side effect to the PUBLIC directive: if a symbol 
  266. is declared PUBLIC in a module, it had better be defined in that 
  267. module.  If it isn't then A86 includes it in the .ERR listing of 
  268. undefined symbols in the module, and suppresses output of the 
  269. object file.
  270.  
  271.  
  272. The EXTRN Directive 
  273.  
  274. Syntax:  EXTRN  sym1:type, sym2:type, ...
  275.  
  276.      where "type" is one of:  BYTE WORD DWORD QWORD TBYTE FAR 
  277.             or synonymously:  B    W    D     Q     T     F
  278.                          or:  NEAR  ABS
  279.  
  280. The EXTRN directive allows you to attach a type to a symbol that 
  281. may not yet be defined (and may never be defined) within your 
  282. program.  This is often necessary for the assembler to generate 
  283. the correct instruction form when the symbol is used as an 
  284. operand.  All the possible types except ABS are defined elsewhere 
  285. in the A86 language, but I list them again here for convenience: 
  286.  
  287.    B or BYTE:  byte-sized memory variable
  288.    W or WORD:  word (2 byte) sized memory variable
  289.    D or DWORD: doubleword (4-byte) sized memory variable
  290.    Q or QWORD: quadword (8-byte) sized memory variable
  291.    T or TWORD: 10-byte-sized memory variable
  292.    NEAR:       program label accessed within a segment
  293.    FAR:        program label accessed from outside this segment
  294.    ABS:        an absolute number (i.e., an immediate constant)
  295.  
  296. An example of EXTRN usage is as follows: suppose there is a word 
  297. memory variable IFARK in your program.  The variable might be 
  298. declared at the end of the program; or it might be defined in a 
  299. module completely outside of this program.  Without an EXTRN 
  300. directive, A86 will assemble an instruction such as "MOV 
  301. AX,IFARK" as the loading of an immediate constant IFARK into the 
  302. AX register.  If you place the directive "EXTRN IFARK:W" at the 
  303. top of your program, you'll get the correct instruction form for 
  304. MOV AX,IFARK-- moving a word memory variable into the AX 
  305. register.  
  306.  
  307. A86 will allow more than one EXTRN directive for a given symbol, 
  308. as long as the same type is given every time.  A86 will even 
  309. allow an EXTRN directive for a symbol that has already been 
  310. defined, as long as the type declared is consistent with the 
  311. symbol's definition.  These allowances exist so that you can 
  312. assemble multiple files written for another assembler, that had 
  313. been fed separately to that assembler.  
  314.                                                           10-7
  315. Note that EXTRN is viewed by A86 quite differently by A86 than by 
  316. other assemblers.  In fact, if it weren't for those other 
  317. assemblers, I'd use the mnemonic DECLARE instead of EXTRN.  A86 
  318. doesn't really use EXTRN to determine which symbols are external-
  319. - it uses those symbols that are undefined at the end of 
  320. assembly.  As I stated earlier in the chapter, an undefined 
  321. symbol can be referenced without being declared via EXTRN.  
  322. Conversely, a defined symbol can be declared (and redeclared) via 
  323. EXTRN; being defined, such a symbol will not be specified 
  324. "external" in the .OBJ file.  
  325.  
  326. Because EXTRN is useful in forward-reference situations, it is 
  327. now recognized even when A86 is assembling a .COM file.  
  328.  
  329. For those of you who are accustomed to the more traditional use 
  330. of EXTRN, and who do not like external records to be created 
  331. "behind your back", A86 offers the "+x" option.  If you include 
  332. "+x" in the program invocation, A86 will require that all 
  333. undefined symbols be explicitly declared via an EXTRN.  Any 
  334. undefined, undeclared symbols will be included in the .ERR 
  335. listing of undefined symbols, and object file output will be 
  336. suppressed.
  337.  
  338.  
  339. MAIN: The Starting Location for a Program
  340.  
  341. I've already stated that exactly one module in a program is the 
  342. "main" module, containing the starting address of the entire 
  343. program.  In A86 when assembling .OBJ files, the starting address 
  344. is given by the label MAIN.  You simply provide the label "MAIN:" 
  345. where you want the program to start.  The module containing MAIN 
  346. is the main module.  
  347.  
  348.  
  349. The END Directive
  350.  
  351. Syntax:  END
  352.          END start_addr
  353.  
  354. The END directive is used by other assemblers for two purposes, 
  355. both of which are now a little silly.  The first purpose is to 
  356. signal the end of assembly.  This was necessary back in the days 
  357. when source files were input on media such as paper tape: you had 
  358. to tell the assembler explicitly that the contents of the tape 
  359. has ended.  Today the operating system can tell you when you've 
  360. reached the end of the file, so this function is an anachronism.  
  361.  
  362. The second purpose of END is, nonsensically, to allow you to 
  363. specify the starting location of the program.  I suppose the 
  364. person who wrote the first assembler back in the 1950's was too 
  365. short on memory to implement a separate START directive, or a 
  366. MAIN label like A86 has, and decided to let END do double-duty.  
  367. I've always considered the example "END START" to have an Alice-
  368. in-Wonderland quality; it is fuel for the high-level-language 
  369. snobs who like to attack assembly language.  Please defeat the 
  370. snobs, and use "MAIN:" if you are writing new code.  
  371.                                                           10-8
  372. For compatibility, A86 treats "END start_addr" exactly the same as 
  373. if you had coded "MAIN EQU start_addr".  Note that if you want 
  374. your program to assemble under both A86 and that other assembler, 
  375. you can specify "END MAIN"-- A86 treats MAIN EQU MAIN as a legal 
  376. redefinition of the symbol MAIN.  
  377.  
  378. A86 ignores END when there is no starting-address operand, thus 
  379. allowing assembly of multiple files written for other assemblers.  
  380.  
  381.  
  382. The SEGMENT Directive
  383.  
  384. Syntax:  seg_name SEGMENT [align] [combine] ['class_name']
  385.  
  386. where "align" is one of:  BYTE   WORD   PARA   PAGE
  387.     "combine" is one of:  PUBLIC  STACK  COMMON  MEMORY  AT number
  388.  
  389. The SEGMENT directive says that assembled object code will 
  390. henceforth go to a block of code whose name is "seg_name".  
  391. "seg_name" is a symbol that represents a value that can be loaded 
  392. into a segment register.  If "seg_name" is not declared in a 
  393. GROUP directive, then its value should in fact be loaded into a 
  394. segment register, in order to address the code.  If "seg_name" is 
  395. declared in a GROUP directive, then the code is a a part of the 
  396. segment addressed by the name of the group.  
  397.  
  398. A program can consist of any number of named segments, to be 
  399. combined in numerous exotic ways to produce the final program.  
  400. You can redirect your object output from one segment to another 
  401. in your assembly, by providing a SEGMENT directive before each 
  402. piece of code.  You can even return to a segment you started 
  403. earlier, by repeating a SEGMENT with the same name-- the 
  404. assembler just picks up where it left off, subject to some 
  405. possible skipping for memory-alignment, that I'll describe 
  406. shortly.  
  407.  
  408. The specifications following the word SEGMENT help to describe 
  409. how the code in this module's part of the segment will be 
  410. combined with code for the same segment name given in other 
  411. modules; and also how this named segment will be grouped with 
  412. other named segments.  Other assemblers require the 
  413. specifications to be given in the order indicated.  A86 will 
  414. accept any order, and will accept commas between the 
  415. specifications if you want to provide them.  The only restriction 
  416. is that "AT number" must be followed by a comma if it is not the 
  417. last specification on the line.  
  418.  
  419. The "align" specification tells if each piece of code within the 
  420. segment should be aligned so that its starting address is an even 
  421. multiple of some number.  BYTE alignment means there is no 
  422. requirement; WORD alignment requires each piece to start at a 
  423.                                                           10-9
  424. multiple of 2; PARA alignment, at a multiple of 16; PAGE 
  425. alignment, at a multiple of 256.  For example, suppose you have a 
  426. segment containing memory variables.  You can declare the segment 
  427. with the statement "VAR_DATA SEGMENT WORD", which insures that 
  428. the segment is aligned to an even memory address.  That way you 
  429. can insure that all 16-bit and bigger memory quantities in the 
  430. segment are aligned to even addresses, for faster access on the 
  431. 16-bit machines of the 86 family.  
  432.  
  433. There are special rules governing alignment for multiple pieces 
  434. of the same named segment within the same program module.  Other 
  435. assemblers outlaw conflicting alignment specifications in this 
  436. situation; A86 accepts them, and uses the strictest specification 
  437. given.  Furthermore, the alignment given for any specification 
  438. beyond the first will control the alignment for that piece of 
  439. code within this module's chunk.  For example, if a program 
  440. contains two pieces of code headed by "VAR_DATA SEGMENT WORD", 
  441. A86 will insert a byte between the pieces if the first piece has 
  442. an odd number of bytes.  This insures correct assembly for 
  443. multiple files written for another assembler.  
  444.  
  445. If no "align" type is given for any of the pieces of a named 
  446. segment, an alignment of PARA is assumed.  
  447.  
  448.  
  449. The "combine" specification tells how the chunk of code from this 
  450. module will be combined with the chunks of the same named 
  451. segment, that come from other modules.  Yes, I know, that sounds 
  452. like what "align" does; but "combine" takes a different, more 
  453. major point of view: 
  454.  
  455. * PUBLIC is the kind of combination we've been talking about all 
  456.   along: each piece of the segment is located off the end of the 
  457.   previously linked piece, subject to possible gaps for 
  458.   alignment.  The size of the segment is the sum of the sizes of 
  459.   the pieces, plus the sizes of the gaps.  
  460.  
  461. * STACK is a combination-type reserved for the system's stack 
  462.   segment.  To illustrate how STACK segment chunks are combined, 
  463.   let's describe the only way a stack segment should ever be 
  464.   used.  We'll call the segment PROG_STACK; and we declare it as 
  465.   follows: 
  466.  
  467.     PROG_STACK SEGMENT WORD STACK
  468.        DW 100 DUP (?)
  469.     TOP_OF_STACK:
  470.  
  471.   The code just given declares a stack area of 200 bytes (100 
  472.   words) for this module.  If identical code occurs in each of 
  473.   three modules which are then linked together, the resulting 
  474.   PROG_STACK segment will have 600 bytes (the sizes are added), 
  475.   but TOP_OF_STACK will be the same address (600) for each module 
  476.   (each piece is overlayed at the top of the segment).  That way, 
  477.   every module can declare and access the top of the stack, which 
  478.   is the only static part of the stack that any code should ever 
  479.   refer to.  
  480.                                                           10-10
  481.  
  482. * COMMON is a type of memory area supported by FORTRAN.  Each 
  483.   module's chunk of a COMMON segment starts at location 0, and 
  484.   overlaps (usually duplicates) the pieces from all the other 
  485.   modules.  The size of a COMMON segment is the size of the 
  486.   largest chunk.  
  487.  
  488. * MEMORY is supposed to be another kind of COMMON segment, that 
  489.   is distinguished by automatically being located beyond all 
  490.   other segments in memory.  The MS_DOS LINK program, however, 
  491.   does not implement MEMORY segments, and instead treats them 
  492.   identically to PUBLIC (not COMMON!) segments.  I can see no 
  493.   useful purpose to the MEMORY combine-type, since the 
  494.   functionality can be achieved by putting a COMMON segment into 
  495.   a 'class' by itself, that goes above all the other classes.  So 
  496.   don't use MEMORY.  
  497.  
  498.   Sorry, I don't support the assembly of multiple files written 
  499.   for other assemblers, that contain STACK, COMMON, or MEMORY 
  500.   segments.  If I did, I would have to detect the file breaks, 
  501.   and duplicate the overlapping functionality of these segment 
  502.   types.  Since I don't think anybody out there is using these 
  503.   esoteric types, I didn't bother to support them to that extent.  
  504.   Objections, anyone?  
  505.  
  506. * "AT number" defines a non-combinable segment at the absolute 
  507.   memory location whose segment register value is "number".  This 
  508.   form is useful for initializing data in fixed locations, such 
  509.   as the 86 interrupt vector (IVECTOR SEGMENT AT 0 followed by 
  510.   ORG 4 * INT_NUMBER), or for reading fixed memory locations, 
  511.   such as the BIOS variables area (BIOS_DATA SEGMENT AT 040).  
  512.  
  513. The combine-type specification can be repeated in subsequent 
  514. pieces of a given segment, but if it is, it must be the same in 
  515. all pieces.  
  516.  
  517. Finally, if no combine-type is ever given for a named segment in 
  518. a module, that segment is non-combinable-- no other modules may 
  519. define that segment; the code given in the one module constitutes 
  520. the entire segment.  
  521.  
  522. The last specification available on a SEGMENT line is the class 
  523. name, which is identified by being enclosed in single quotes.  
  524. Unlike a segment name, which can be used as an instruction 
  525. operand an hence cannot conflict with other assembler symbols, a 
  526. class name can be assigned without regard to its usage elsewhere 
  527. in the program.  It can even be a built-in A86 mnemonic.  In 
  528. fact, both the SMALL and LARGE high-level-language models specify 
  529. the class name 'CODE' for code segments, and the SMALL model 
  530. specifies the class name 'DATA'.  
  531.  
  532. If no class name is given for a segment, A86 specifies the null 
  533. (zero-length) string as the class name.  
  534.                                                           10-11
  535. DATA SEGMENT, STRUC and CODE SEGMENT Directives
  536.  
  537. The DATA SEGMENT and STRUC directives work in .OBJ mode exactly 
  538. as they do in .COM mode-- they define a special assembly mode, in 
  539. which declarations are made, but no object code is output.  
  540. Offsets within DATA segments and structures are absolute, as in 
  541. .COM mode.  Assembly resumes as before when an ENDS or CODE 
  542. SEGMENT directive is encountered.  
  543.  
  544.  
  545. The ENDS Directive
  546.  
  547. Syntax:  [seg_name] ENDS
  548.  
  549. The ENDS directive closes out the segment currently being 
  550. assembled, and returns assembly to the segment being assembled 
  551. before the last SEGMENT directive.  The "seg_name", if given, 
  552. must match the name in that last SEGMENT directive.  ENDS allows 
  553. you to "nest" segments inside one another.  For example, you can 
  554. declare some static data variables that are specific to a certain 
  555. section of code at the top of that section: 
  556.  
  557.   _DATA SEGMENT BYTE PUBLIC 'DATA'
  558.     VAR1  DB ?
  559.     VAR2  DB ?
  560.   _DATA ENDS
  561.  
  562. These four lines can be inserted inside any other segment being 
  563. assembled.  They will cause the two variable allocations to be 
  564. tacked onto the segment _DATA; and assembly will then continue in 
  565. whatever segment surrounded the four lines.  Observe that the 
  566. "nesting" does not occur in the final program; only the 
  567. presentation of the source code is nested.  
  568.  
  569. If you are not nesting segments inside one another, then the ENDS 
  570. directive serves only to lend a clean, "block-structured" 
  571. appearance to your source code.  It does not assist A86 in any 
  572. particular way; in fact, it consumes a bit more object output 
  573. memory (slightly reducing object output capacity) if you have 
  574. ENDSs, rather than just starting up new segments with SEGMENT 
  575. directives.  
  576.  
  577.  
  578. Default Outer SEGMENT
  579.  
  580. Other assemblers outlaw any code outside of a SEGMENT 
  581. declaration, forcing you to give a SEGMENT declaration before you 
  582. can assemble anything.  A86 lets you assemble just your code; you 
  583. don't have to worry about SEGMENTs if you don't want to.  
  584.  
  585. If you do provide code outside of all SEGMENT declarations, A86 
  586. performs the following steps, to find a reasonable place to put 
  587. the code: 
  588.  
  589. 1. If there are any segments explicitly declared whose name is or 
  590.    ends with "_TEXT", then the first such segment declared is 
  591.    used.  It is as if the SEGMENT declaration appeared at the top 
  592.    of, rather than within, the program.  
  593.                                                           10-12
  594. 2. If there is no such explicit segment, A86 creates a BYTE 
  595.    PUBLIC segment of class 'CODE', and proceeds to construct a 
  596.    name for the segment.  If there are no RETF instructions in 
  597.    the outer segment, the name chosen is "_TEXT", conforming to 
  598.    the SMALL model of computation.  If there is a RETF 
  599.    instruction, the name chosen is "modulename_TEXT", where 
  600.    "modulename" is the name of this module.  Recall that 
  601.    "modulename" comes from the NAME directive if there is one; 
  602.    from the name of the .OBJ file if there isn't.  
  603.  
  604.  
  605. The GROUP Directive
  606.  
  607. Syntax:  group_name GROUP seg_name1, seg_name2, ...
  608.  
  609. The GROUP directive causes A86 to tell LINK that all the listed 
  610. segments can fit into a single 64K-byte block of memory, and 
  611. instruct LINK to make that fit.  (If they won't fit, LINK will 
  612. issue an error message.)  Having declared the group, you can then 
  613. use "group_name" as the segment register value that will allow 
  614. simultaneous access to all the named segments.  The order of 
  615. names given in the list does not necessarily determine the order 
  616. the segments will finally appear within the group.  
  617.  
  618. The most useful application of the GROUP directive is to allow 
  619. you to structure the pieces of a program, all of whose code and 
  620. data will fit into a single 64K segment.  You organize the pieces 
  621. into SEGMENTs, and declare all the SEGMENTs to be within the same 
  622. GROUP.  When the program starts, all segment registers are set to 
  623. point to the GROUP, and you never have to worry about segment 
  624. registers again in the program.  
  625.  
  626. WARNING: If your segments will be GROUPed in the final program, 
  627. you should have the appropriate GROUP directive in every module 
  628. assembled.  If you don't, then any memory pointers generated will 
  629. be relative to the beginning of the individual named segments, 
  630. not to the beginning of the whole group.  
  631.  
  632. Because of the obscure scenario I described in the Overview 
  633. section, Intel does not prohibit more than one GROUP from 
  634. containing some of the same segments; so neither does A86.  Any 
  635. pointers within a segment will be calculated from the beginning 
  636. of the last GROUP that the segment was declared within.  But 
  637. again, I have my doubts as to whether LINK will handle this 
  638. correctly.  
  639.  
  640.  
  641.